package io.zbc.ai.spring.ai.demo.chat.client.controller;

import java.util.List;
import java.util.stream.Collectors;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.converter.BeanOutputConverter;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

/**
 * @author zbc
 * @date 2025/4/28
 */
@RestController
@RequestMapping("/stream")
public class StreamChatController {

  private final ChatClient chatClient;

  public StreamChatController(ChatClient chatClient) {
    this.chatClient = chatClient;
  }

  /**
   * 流的方式返回文本
   *
   * @param msg
   * @return
   */
  @GetMapping(value = "/chat", produces = "text/html;charset=UTF-8")
  public Flux<String> chat(@RequestParam("msg") String msg) {
    Flux<String> output = chatClient.prompt().user(msg).stream().content();
    return output;
  }

  /**
   * format
   *
   * @param msg
   * @return
   */
  @GetMapping(value = "/chatFormat")
  public List<ActorFilms> chatFormat(@RequestParam("msg") String msg) {
    var converter =
        new BeanOutputConverter<>(new ParameterizedTypeReference<List<ActorFilms>>() {});
    Flux<String> flux =
        this.chatClient
            .prompt()
            .user(
                u ->
                    u.text(
                            String.format(
                                """
                        %s
                        {format}
                      """,
                                msg))
                        .param("format", converter.getFormat()))
            .stream()
            .content();

    String content = flux.collectList().block().stream().collect(Collectors.joining());

    List<ActorFilms> actorFilms = converter.convert(content);
    return actorFilms;
  }

  record ActorFilms(String actor, List<String> movies) {}
}
